// Copyright 2009 Thiago H. de Paula Figueiredo
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package br.com.arsmachina.authorization.impl;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import br.com.arsmachina.authorization.ReadObjectAuthorizationException;
import br.com.arsmachina.authorization.ReadTypeAuthorizationException;
import br.com.arsmachina.authorization.RemoveObjectAuthorizationException;
import br.com.arsmachina.authorization.RemoveTypeAuthorizationException;
import br.com.arsmachina.authorization.SearchTypeAuthorizationException;
import br.com.arsmachina.authorization.SingleTypeAuthorizer;
import br.com.arsmachina.authorization.StoreTypeAuthorizationException;
import br.com.arsmachina.authorization.UpdateObjectAuthorizationException;
import br.com.arsmachina.authorization.UpdateTypeAuthorizationException;

/**
 * Class that implements all {@link SingleTypeAuthorizer} <code>check</code>
 * exceptions.
 * 
 * @param <T> the type covered by this authorizer.
 * @author Thiago H. de Paula Figueiredo
 */
public abstract class AbstractSingleTypeAuthorizer<T> implements
		SingleTypeAuthorizer<T> {

	final private Class<T> clasz;

	/**
	 * Constructor that receives the authorized type.
	 * 
	 * @param clasz a {@link Class} instance. It cannot be null.
	 */
	protected AbstractSingleTypeAuthorizer(Class<T> clasz) {

		if (clasz == null) {
			throw new IllegalArgumentException("Parameter clasz cannot be null");
		}

		this.clasz = clasz;

	}

	/**
	 * Constructor without arguments.
	 */
	@SuppressWarnings("unchecked")
	public AbstractSingleTypeAuthorizer() {

		Type genericSuperclass = getClass().getGenericSuperclass();

		final ParameterizedType parameterizedType =
			((ParameterizedType) genericSuperclass);
		clasz = (Class<T>) parameterizedType.getActualTypeArguments()[0];

		assert clasz != null;

	}

	public void checkRead() {

		if (canRead() == false) {
			throw new ReadTypeAuthorizationException(clasz);
		}

	}

	public void checkRead(T object) {

		if (canRead(object) == false) {
			throw new ReadObjectAuthorizationException(object);
		}

	}

	public void checkRemove() {

		if (canRemove() == false) {
			throw new RemoveTypeAuthorizationException(clasz);
		}

	}

	public void checkRemove(T object) {

		if (canRemove(object) == false) {
			throw new RemoveObjectAuthorizationException(object);
		}

	}

	public void checkSearch() {

		if (canSearch() == false) {
			throw new SearchTypeAuthorizationException(clasz);
		}

	}

	public void checkStore() {

		if (canStore() == false) {
			throw new StoreTypeAuthorizationException(clasz);
		}

	}

	public void checkUpdate() {

		if (canUpdate() == false) {
			throw new UpdateTypeAuthorizationException(clasz);
		}

	}

	public void checkUpdate(T object) {

		if (canUpdate(object) == false) {
			throw new UpdateObjectAuthorizationException(object);
		}

	}

	/**
	 * Retorna o valor da propriedade <code>clasz</code>.
	 * 
	 * @return o valor de <code>clasz</code>.
	 */
	final public Class<T> getAuthorizedClass() {
		return clasz;
	}

}
